package com.zkingsoft.common.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.matrix.core.constance.MatrixConstance;
import com.matrix.core.constance.SystemErrorCode;
import com.matrix.core.exception.GlobleException;
import com.matrix.core.pojo.PaginationVO;
import com.matrix.core.tools.ModelUtils;
import com.matrix.core.tools.StringUtils;
import com.matrix.core.tools.UUIDUtil;
import com.matrix.core.tools.WebUtil;
import com.zkingsoft.common.authority.DefaultAuthorityManager;
import com.zkingsoft.common.bean.SysFnBtnRel;
import com.zkingsoft.common.bean.SysFunction;
import com.zkingsoft.common.bean.SysUsers;
import com.zkingsoft.common.constance.AppConstance;
import com.zkingsoft.common.constance.AppMessageCode;
import com.zkingsoft.common.dao.SysFunctionDao;
import com.zkingsoft.common.service.SysFunctionService;
import com.zkingsoft.common.tools.ServiceUtil;

/**
 * 系统功能管理
 * 
 * @author jiangyouyao
 * @time 2016-11-18
 */
@Service
public class SysFunctionServiceImpl implements SysFunctionService {

	@Autowired
	private SysFunctionDao sysFunctionDao;

	@Autowired
	private ServiceUtil serviceUtil;

	@Resource
	private DefaultAuthorityManager matrix;

	private String tableName = "sys_function";

	Logger log = Logger.getLogger(this.getClass());

	@Transactional
	@Override
	public int add(SysFunction sysFunction) {
		
		// 自己不能是自己的父节点
		if (sysFunction.getFnParentId() != null && sysFunction.getFnParentId().equals(sysFunction.getFnId())) {
			throw new GlobleException(AppMessageCode.Function.PARENT_FUNCTION_CANNOT_BE_SELF);
		}
		// 功能code去重
		if (serviceUtil.addCheckRepeat(tableName, "fn_code", sysFunction.getFnCode())) {
			throw new GlobleException(SystemErrorCode.DATA_REPEAT, sysFunction.getFnCode());
		}
		sysFunction.setFnId(UUIDUtil.getRandomID());
		SysUsers user = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY);
		sysFunction.setCreateBy(user.getSuName());
		sysFunction.setUpdateBy(user.getSuName());
		// 设置功能等级
		setFunctionGrade(sysFunction);
		sysFunction.setFnIsDisable(AppConstance.IS_N);
		// 添加功能所对应的按钮
		addFnBtnRel(sysFunction);

		return sysFunctionDao.insert(sysFunction);

	}

	/**
	 * 添加功能所对应的按钮
	 * 
	 * @author JIANGYOUYAO
	 * @param fnId
	 * @email 935090232@qq.com
	 * @date 2017年12月4日
	 * @param sysFunction
	 */
	private void addFnBtnRel(SysFunction function) {
		List<SysFnBtnRel> rels = function.getSysFnBtnRel();
		List<SysFnBtnRel> newRels = new ArrayList<>();
		for (SysFnBtnRel sysFnBtnRel : rels) {
			if (sysFnBtnRel.getBtnValue() == null) {
				continue;
			}
			sysFnBtnRel.setFnId(function.getFnId());
			sysFnBtnRel.setCreateBy(function.getCreateBy());
			sysFnBtnRel.setUpdateBy(function.getUpdateBy());
			newRels.add(sysFnBtnRel);
		}
		if (CollectionUtils.isNotEmpty(newRels)) {
			sysFunctionDao.bathInsertFnButRel(newRels);
		}
	}

	/**
	 * 删除功能所对应的按钮
	 * 
	 * @author JIANGYOUYAO
	 * @email 935090232@qq.com
	 * @date 2017年12月4日
	 * @param fnId
	 */
	private void removerFnBtnRel(String fnId) {
		sysFunctionDao.deleteFnBtnRel(fnId);
	}

	/**
	 * 批量删除功能所对应的按钮
	 * 
	 * @author JIANGYOUYAO
	 * @email 935090232@qq.com
	 * @date 2017年12月4日
	 * @param fnId
	 */
	private void batchRemoverFnBtnRel(List<String> ids) {

		sysFunctionDao.deleteFnBtnRels(ids);
	}

	/**
	 * 设置功能的等级
	 * 
	 * @author JIANGYOUYAO
	 * @email 935090232@qq.com
	 * @date 2017年12月4日
	 * @param sysFunction
	 */
	private void setFunctionGrade(SysFunction sysFunction) {
		if (StringUtils.isBlank(sysFunction.getFnParentId())) {
			sysFunction.setFnGrade(AppConstance.FUNCTION_FIRST_LEVEL);
		} else {
			SysFunction parent = sysFunctionDao.selectById(sysFunction.getFnParentId());
			sysFunction.setFnGrade(parent.getFnGrade() + 1);
		}
	}

	@Override
	public int batchAdd(List<SysFunction> sysFunctionList) {
		return sysFunctionDao.batchInsert(sysFunctionList);
	}

	@Transactional
	@Override
	public int modifyByMap(SysFunction oldSysFunction, SysFunction newSysFunction) {
		// 自己不能是自己的父节点
		if (newSysFunction.getFnParentId() != null && newSysFunction.getFnParentId().equals(newSysFunction.getFnId())) {
			throw new GlobleException("功能的父级不能是自己");
		}
		// 功能code去重
		if (serviceUtil.updateCheckRepeat(tableName, "fn_code", newSysFunction.getFnCode(), "fn_id",
				newSysFunction.getFnId())) {
			throw new GlobleException("code已经存在！");
		}
		// 设置功能等级
		setFunctionGrade(newSysFunction);
		SysUsers user = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY);
		// 创建人的复制是为了按钮关系表能够赋值
		newSysFunction.setCreateBy(oldSysFunction.getCreateBy());
		newSysFunction.setUpdateBy(user.getSuName());
		Map<String, Object> modifyMap = null;
		int dmlResult = 0;
		try {
			if (!ModelUtils.isModified(oldSysFunction, newSysFunction)) {
				return MatrixConstance.DML_SUCCESSS;
			}
			modifyMap = ModelUtils.comparePojo2Map(oldSysFunction, newSysFunction);
		} catch (Exception e) {
			throw new GlobleException(SystemErrorCode.DATA_UPDATE_FAIL, e, newSysFunction.getFnName());
		}
		if (modifyMap.size() > 0) {
			modifyMap.put("fnId", oldSysFunction.getFnId());
			dmlResult = sysFunctionDao.updateByMap(modifyMap);
		}
		removerFnBtnRel(oldSysFunction.getFnId());
		addFnBtnRel(newSysFunction);
		return dmlResult;
	}

	@Override
	@Transactional
	public int modifyByModel(SysFunction sysFunction) {

		return sysFunctionDao.updateByModel(sysFunction);

	}

	@Override
	public int remove(List<String> list) {
		int count = 0;
		for (String fnId : list) {
			removeById(fnId);
			count++;
		}
		return count;
	}

	/**
	 * 删除功能和功能下的子功能
	 * 
	 * @param fnId
	 * @return
	 */
	@Override
	@Transactional
	public int removeById(String fnId) {
		if (fnId == null) {
			return 0;
		}
		List<String> ids = getFunctionChirds(fnId, new ArrayList<String>());
		if (CollectionUtils.isNotEmpty(ids)) {
			batchRemoverFnBtnRel(ids);
		}
		return sysFunctionDao.deleteByIds(ids);
	}

	@Override
	public int removeByModel(SysFunction sysFunction) {

		return sysFunctionDao.deleteByModel(sysFunction);

	}

	@Override
	public List<SysFunction> findInPage(SysFunction sysFunction, PaginationVO pageVo) {

		return sysFunctionDao.selectInPage(sysFunction, pageVo);

	}

	@Override
	public List<SysFunction> findByModel(SysFunction sysFunction) {

		return sysFunctionDao.selectByModel(sysFunction);

	}

	@Override
	public int findTotal(SysFunction sysFunction) {

		return sysFunctionDao.selectTotalRecord(sysFunction);

	}

	@Override
	public SysFunction findById(String fnId) {

		return sysFunctionDao.selectById(fnId);

	}

	/**
	 * 获取功能下的子功能id，包含功能自己的id
	 * 
	 * @param id
	 * @param ids
	 * @return
	 */
	private List<String> getFunctionChirds(String id, List<String> ids) {
		SysFunction fnquery = new SysFunction();
		fnquery.setFnParentId(id);
		// 获取子节点
		List<SysFunction> list = sysFunctionDao.selectByModel(fnquery);
		if (!list.isEmpty()) {
			for (SysFunction function : list) {
				// 删除子节点
				getFunctionChirds(function.getFnId(), ids);
			}
		}
		ids.add(id);
		return ids;
	}

	@Override
	public void setIsDisable(String fnId, String status) {
		SysFunction dbFunction = sysFunctionDao.selectById(fnId);
		if (status.equals(AppConstance.IS_Y)) {
			// 启用功能
			if (dbFunction.getFnIsDisable().equals(AppConstance.IS_Y)) {
				throw new GlobleException("功能已经是启用状态");
			} else {

				List<String> list = getFunctionChirds(fnId, new ArrayList<String>());
				sysFunctionDao.batchChangeStatu(AppConstance.IS_Y, list);
			}
		} else {
			// 禁用功能
			if (dbFunction.getFnIsDisable().equals(AppConstance.IS_N)) {
				throw new GlobleException("功能已是禁用状态");
			} else {

				// 启用子节点,和父节点，因为目前只考虑2级的情况先写死吧
				List<String> ids = new ArrayList<String>();
				if (dbFunction.getFnParentId() != null) {
					ids.add(dbFunction.getFnParentId());
				}
				sysFunctionDao.batchChangeStatu(AppConstance.IS_N, getFunctionChirds(fnId, ids));

			}
		}

	}

	@Override
	public List<SysFunction> findCompanyFunction(String companyId) {
		return sysFunctionDao.selectCompanyFunction(companyId);
	}

	@Override
	public List<SysFunction> findFunctionByRoleIds(String roleIds) {
		return sysFunctionDao.selectFunctionByRoleIds(roleIds);
	}

	@Override
	public List<SysFunction> findRoleFuntion(String roleId) {
		// 获取所有的功能--》获取所有的按钮--》对于功能的按钮|构建功能的父子关系--》
		Map<String, SysFunction> roleFnMap = new HashMap<>(MatrixConstance.COLLECTION_SIZE);
		// id为空则不需要查询选中项
		if (roleId != null) {
			// 把角色所有的功能变成map
			List<SysFunction> editorFunction = sysFunctionDao.selectFunctionByRoleIds(roleId);
			for (SysFunction temp : editorFunction) {
				roleFnMap.put(temp.getFnId(), temp);
			}
		}

		// 只查询出没有被禁用的
		SysUsers user = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY);
		// 只能查本公司的
		List<SysFunction> allFunction = sysFunctionDao.selectCompanyFunction(user.getCompanyId());
		Map<String, SysFunction> allFnMap = new TreeMap<>();
		// 构建树形关系
		for (SysFunction sysFunction : allFunction) {
			// 用一个map记录下每一个功能
			allFnMap.put(sysFunction.getFnId(), sysFunction);
		}

		List<SysFunction> treeFunction = new ArrayList<>();
		Set<String> keys = allFnMap.keySet();
		for (String currentFnId : keys) {

			SysFunction function = allFnMap.get(currentFnId);

			// 判断功能是否为当前角色拥有
			initHashPower(roleFnMap, currentFnId, function);

			// 如果是一级节点则直接存入菜单
			if (StringUtils.isBlank(function.getFnParentId())) {
				treeFunction.add(function);
			} else {
				// 非一级节点找到父节点后存入
				SysFunction parentFn = allFnMap.get(function.getFnParentId());
				List<SysFunction> childs = parentFn.getChilds();
				if (childs == null) {
					parentFn.setChilds(new ArrayList<SysFunction>());
				}
				parentFn.getChilds().add(function);
			}

		}
		return treeFunction;
	}

	/**
	 * 给已经拥有的权限打上标记
	 * 
	 * @author JIANGYOUYAO
	 * @email 935090232@qq.com
	 * @date 2017年12月6日
	 * @param roleFnMap
	 * @param currentFnId
	 * @param function
	 */
	private void initHashPower(Map<String, SysFunction> roleFnMap, String currentFnId, SysFunction function) {
		if (roleFnMap.containsKey(currentFnId)) {
			// 功能是当前角色拥有的
			function.setHasThisFn(true);
			// 判断按钮是否为当前角色拥有
			String rpfBns = roleFnMap.get(currentFnId).getRpfBns();
			String[] rpfBnsArray = rpfBns.split(",");

			List<SysFnBtnRel> fnBtnRelList = function.getSysFnBtnRel();

			if (CollectionUtils.isNotEmpty(fnBtnRelList) && ArrayUtils.isNotEmpty(rpfBnsArray)) {

				for (SysFnBtnRel fnBtnRel : fnBtnRelList) {
					for (String tempRpfBns : rpfBnsArray) {
						if (fnBtnRel.getBtnValue().equals(tempRpfBns)) {
							fnBtnRel.setHasThisBtn(true);
							break;
						}
					}

				}
			}
		}
	}

}